package main

import (
	"encoding/json"
	"fmt"
	"ichain/protos/ledger/queryresult"

	"ichain/contract/stub"
	pb "ichain/protos/inode"
)

type ObtainContract struct {
}

type Result struct {
	Success bool `json:"success"`
	Msg string `json:"msg"`
	Data interface{} `json:"data,omitempty"`
}

func (t *ObtainContract) Init(stubif stub.ContractStub) pb.Response {
	return stub.Success(nil)
}

func (t *ObtainContract) Invoke(stubif stub.ContractStub) pb.Response {
	fn, args := stubif.GetFunctionAndParameters()
	var result string
	var err error
	if fn == "setData" {
		result, err = setData(stubif, args)
	} else if fn == "getData" {
		result, err = getData(stubif, args)
	} else if fn == "getHistory" {
		result, err = getHistory(stubif, args)
	}
	if err != nil {
		return stub.Error(err.Error())
	}
	return stub.Success([]byte(result))
}

func setData(stubif stub.ContractStub, args []string) (string, error) {
	err := stubif.PutState(args[0], []byte(args[1]))
	if err != nil {
		return getResult(false, fmt.Sprintf("ObtainContract setData failed key:%s--value:%s", args[0], args[1])), nil
	}
	return getResult(true, "存证成功"), nil
}


func getData(stubif stub.ContractStub, args []string) (string, error) {
	value, err := stubif.GetState(args[0])
	if err != nil {
		return getResult(false, fmt.Sprintf("ObtainContract getData failed key:%s", args[0])), nil
	}
	if value == nil {
		return getResult(false, "获取失败，该记录不存在"), nil
	}
	return getResult(true, "获取成功", string(value)), nil
}

func getResult(success bool, msg string, data ...interface{}) string {
	result := Result{success, msg, nil}
	if  len(data) >= 1 {
		result.Data = data[0]
	}
	bytes, _ := json.Marshal(result)
	return string(bytes)
}

func getHistory(stubif stub.ContractStub, args []string) (string, error) {
	it, err := stubif.GetHistoryForKey(args[0])
	if err != nil {
		return "", err
	}
	result, err := getHistoryListResult(it)
	return result, err
}

func getHistoryListResult(resultsIterator stub.HistoryQueryIteratorInterface) (string, error) {
	defer resultsIterator.Close()

	data := make([]*queryresult.KeyModification, 0)
	for resultsIterator.HasNext() {
		queryResponse, err := resultsIterator.Next()
		if err != nil {
			return "", err
		}
		data = append(data, queryResponse)
	}

	return getResult(true, "获取成功", data), nil
}

func main() {
	if err := stub.Start(new(ObtainContract)); err != nil {
		fmt.Printf("Error starting ObtainContract: %s", err)
	}
}
